/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dancrawler.sound;

import dancrawler.common.Misc;
import dancrawler.db.Database;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

/**
 * Sound playback subsystem for Dancrawler, depends on Database
 * Code heavily dependant on code from vorbisspi-103
 * @author Team 4 RMI, HINGDA10
 */
public class SoundBank {

  Map<String, Sound> sounds = new HashMap();
  Database db;

  /**
   * Initializes sound sample index from database
   */
  public SoundBank() {
    if (sounds.isEmpty()) {
      db = new Database();
      sounds = db.getSoundsFromSQL();
    }
  }

  private class Player extends Thread {

    public String fileName;

    @Override
    public void run() {
      AudioInputStream in = null;
      try {
        File file = new File(fileName);
        in = AudioSystem.getAudioInputStream(file);
        AudioInputStream din = null;
        if (in != null) {
          AudioFormat baseFormat = in.getFormat();
          AudioFormat decodedFormat = new AudioFormat(
                  AudioFormat.Encoding.PCM_SIGNED,
                  baseFormat.getSampleRate(),
                  16,
                  baseFormat.getChannels(),
                  baseFormat.getChannels() * 2,
                  baseFormat.getSampleRate(),
                  false);
          din = AudioSystem.getAudioInputStream(decodedFormat, in);
          try {
            rawplay(decodedFormat, din);
          } catch (LineUnavailableException ex) {
          }
          in.close();
        }
      } catch (UnsupportedAudioFileException ex) {
      } catch (IOException ex) {
      } finally {
        try {
          in.close();
        } catch (IOException ex) {
        }
      }
    }
  }

  private void rawplay(AudioFormat targetFormat,
          AudioInputStream din) throws IOException, LineUnavailableException {
    byte[] data = new byte[4096];
    SourceDataLine line = getLine(targetFormat);
    if (line != null) {
      line.start();
      int nBytesRead = 0, nBytesWritten = 0;
      while (nBytesRead != -1) {
        nBytesRead = din.read(data, 0, data.length);
        if (nBytesRead != -1) {
          nBytesWritten = line.write(data, 0, nBytesRead);
        }
      }
      line.drain();
      line.stop();
      line.close();
      din.close();
    }
  }

  private SourceDataLine getLine(AudioFormat audioFormat) throws LineUnavailableException {
    SourceDataLine res = null;
    DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
    res = (SourceDataLine) AudioSystem.getLine(info);
    res.open(audioFormat);
    return res;
  }

  /**
   * Gets file path in data folder from event by sound mapping triggered earlier
   * Starts sound player thread
   * @param event Event code triggered by game action
   */
  public void PlaySound(String event) {
    String soundfile = Misc.getAppdataPath(File.separatorChar + "dancrawler")+File.separatorChar + sounds.get(event).getFilename() + ".wav";
    System.out.println(soundfile);
    Player playerThread = new Player();
    playerThread.fileName = soundfile;
    playerThread.setDaemon(true);
    playerThread.start();
  }
}
